package com.yycx.starter.fileview.conver;

import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.aspectj.util.FileUtil;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 文件转换工具类
 */
@Slf4j
public class PdfUtils {

    //将word转PDF
    public static void wordToPdf(String wordPath, String pdfPath) throws Exception {
        Document doc = new Document(wordPath);
        doc.save(pdfPath, SaveFormat.PDF);
    }

    //文件转成图片
    public static void fileToImage(String sourceFilePath, String imagePath) throws Exception {
        String ext = sourceFilePath.substring(sourceFilePath.lastIndexOf("."));
        switch (ext) {
            case ".doc":
            case ".docx":
                wordToImage(sourceFilePath, imagePath);
                break;
            case ".pdf":
                pdfToImage(sourceFilePath, imagePath);
                break;
            case ".txt":
                txtToImage(sourceFilePath, imagePath);
                break;
            default:
                System.out.println("文件格式不支持");
        }
    }

    //将pdf转成图片
    public static void pdfToImage(String pdfPath, String imagePath) throws Exception {
        File file = new File(pdfPath);
        String filename = file.getName();
        String pathPre = imagePath + File.separator + filename.substring(0, filename.lastIndexOf("."));
        PDDocument doc = PDDocument.load(file);
        PDFRenderer renderer = new PDFRenderer(doc);
        for (int i = 0; i < doc.getNumberOfPages(); i++) {
            BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
            String pathname = pathPre + (i + 1) + ".png";
            ImageIO.write(image, "PNG", new File(pathname));
        }
        doc.close();
    }

    //将word转成图片
    public static void wordToImage(String wordPath, String imagePath) throws Exception {
        Document doc = new Document(wordPath);
        File file = new File(wordPath);
        String filename = file.getName();
        String pathPre = imagePath + File.separator + filename.substring(0, filename.lastIndexOf("."));
        for (int i = 0; i < doc.getPageCount(); i++) {
            Document extractedPage = doc.extractPages(i, 1);
            String path = pathPre + "/" + (i + 1) + ".png";
            extractedPage.save(path, SaveFormat.PNG);
        }
    }

    //pdf转成图片(多线程)
    public static void pdfToImageAsync(String pdfPath, String imagePath) throws Exception {
        long old = System.currentTimeMillis();
        File file = new File(pdfPath);
        PDDocument doc = PDDocument.load(file);
        PDFRenderer renderer = new PDFRenderer(doc);
        int pageCount = doc.getNumberOfPages();
        int numCores = Runtime.getRuntime().availableProcessors();
        ExecutorService executorService = Executors.newFixedThreadPool(numCores);
        for (int i = 0; i < pageCount; i++) {
            int finalI = i;
            executorService.submit(() -> {
                try {
                    BufferedImage image = renderer.renderImageWithDPI(finalI, 144); // Windows native DPI
                    String filename = file.getName();
                    filename = filename.substring(0, filename.lastIndexOf("."));
                    String pathname = imagePath + File.separator + filename + (finalI + 1) + ".png";
                    ImageIO.write(image, "PNG", new File(pathname));
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
        }
        executorService.shutdown();
        executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        doc.close();
        long now = System.currentTimeMillis();
        System.out.println("pdfToImage 多线程 转换完成..用时：" + (now - old) + "ms");
    }

    //将word转成图片(多线程)
    public static void wordToImageAsync(String wordPath, String imagePath) throws Exception {
        Document doc = new Document(wordPath);
        File file = new File(wordPath);
        String filename = file.getName();
        String pathPre = imagePath + File.separator + filename.substring(0, filename.lastIndexOf("."));
        int numCores = Runtime.getRuntime().availableProcessors();
        ExecutorService executorService = Executors.newFixedThreadPool(numCores);
        for (int i = 0; i < doc.getPageCount(); i++) {
            int finalI = i;
            executorService.submit(() -> {
                try {
                    Document extractedPage = doc.extractPages(finalI, 1);
                    String path = pathPre + (finalI + 1) + ".png";
                    extractedPage.save(path, SaveFormat.PNG);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
        }
    }


    //txt转成转成图片
    public static void txtToImage(String txtPath, String imagePath) throws Exception {
        wordToImage(txtPath, imagePath);
    }


    //将txt转成图片(多线程)
    public static void txtToImageAsync(String txtPath, String imagePath) throws Exception {
        wordToImageAsync(txtPath, imagePath);
    }


    //将文件转成图片流
    public static List<byte[]> fileToImageStream(String pdfPath) throws Exception {
        String ext = pdfPath.substring(pdfPath.lastIndexOf("."));
        switch (ext) {
            case ".doc":
            case ".docx":
                return wordToImageStream(pdfPath);
            case ".pdf":
                return pdfToImageStream(pdfPath);
            case ".txt":
                return txtToImageStream(pdfPath);
            default:
                System.out.println("文件格式不支持");
        }
        return null;
    }

    //将pdf转成图片流
    public static List<byte[]> pdfToImageStream(String pdfPath) throws Exception {
        File file = new File(pdfPath);
        PDDocument doc = PDDocument.load(file);
        PDFRenderer renderer = new PDFRenderer(doc);
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < doc.getNumberOfPages(); i++) {
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
                ImageIO.write(image, "PNG", outputStream);
                list.add(outputStream.toByteArray());
            }
        }
        doc.close();
        return list;
    }

    //将word转成图片流
    public static List<byte[]> wordToImageStream(String wordPath) throws Exception {
        Document doc = new Document(wordPath);
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < doc.getPageCount(); i++) {
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                Document extractedPage = doc.extractPages(i, 1);
                extractedPage.save(outputStream, SaveFormat.PNG);
                list.add(outputStream.toByteArray());
            }
        }
        return list;
    }

    /**
     * 将txt转成图片流
     *
     * @param txtPath
     * @return
     * @throws Exception
     */
    public static List<byte[]> txtToImageStream(String txtPath) throws Exception {
        return wordToImageStream(txtPath);
    }

    public static void ImageToPdf(String imageBasePath, String pdfPath) {
        // 创建一个Document对象
        com.itextpdf.text.Document document = new com.itextpdf.text.Document();
        try {
            // 指定pdf文件的输出路径
            PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
            String[] images = FileUtil.listFiles(new File(imageBasePath));
            document.open();
            // 添加每张图片到pdf文件
            for (String path : images) {
                // 读取图片
                Image image = Image.getInstance(path);
                // 设置图片大小
                image.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());
                // 添加图片到pdf
                document.add(image);
            }
            document.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param imageFolderPath 图片文件夹地址
     * @param pdfPath         PDF文件保存地址
     */
    public static void toPdf(String imageFolderPath, String pdfPath) {
        try {
            log.info("#############################开始转pdf{}", pdfPath);
            // 图片地址
            String imagePath = null;
            // 输入流
            FileOutputStream fos = new FileOutputStream(pdfPath);
            // 创建文档
            com.itextpdf.text.Document doc = new com.itextpdf.text.Document();
            //doc.open();
            // 写入PDF文档
            PdfWriter.getInstance(doc, fos);
            // 获取图片文件夹对象
            File file = new File(imageFolderPath);
            File[] files = file.listFiles();
            // 添加图片到文档
            doc.open();
            // 根据图片大小设置文档大小

            // 循环获取图片文件夹内的图片
            for (File file1 : files) {
                imagePath = imageFolderPath + "/" + file1.getName();
                // 实例化图片
                Image image = Image.getInstance(imagePath);
                image.scaleToFit(image.getWidth(), image.getHeight());
                doc.add(image);
            }
            // 关闭文档
            doc.close();
            log.info("#############################PDF转换成功", pdfPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将图片转换成PDF
     *
     * @param source 文件路径的集合 可以调用 FileUtil.getFileList() 方法
     * @param target PDF的名字和位置
     */
    public static void ImgChangePDF(String[] source, String target) throws Exception {
        //创建一个文档对象
        com.itextpdf.text.Document doc = new com.itextpdf.text.Document();
        try {
            //定义输出文件的位置
            PdfWriter.getInstance(doc, new FileOutputStream(target));
            //开启文档
            doc.open();

            // 创建一个一行两列的表格
            PdfPTable table = new PdfPTable(2);
            for (int i = 0; i < source.length; i++) {
                if (source[i] == null) {
                    break;
                }
                Image img = Image.getInstance(source[i]);
                Float h = img.getHeight();
                Float w = img.getWidth();
                Integer percent = getPercent(h, w);
                img.setAlignment(Image.MIDDLE);
                img.scalePercent(percent);
                PdfPCell cell = new PdfPCell(img); // 将图片放置在单元格中
                cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 设置单元格中的内容居中对齐
                cell.setBorder(Rectangle.NO_BORDER); // 去掉单元格的边框
                cell.setFixedHeight(200f); // 设置单元格的固定高度
                cell.setBorderWidth(300f); // 设置单元格的固定宽度
                table.addCell(cell); // 将单元格添加到表格中
            }
            doc.add(table); // 将表格添加到文档中

            // 循环获取图片文件夹内的图片（一行一列）
            /*for (int i = 0; i < source.length; i++) {
                if(source[i] == null){      //前面的方法默认了数组长度是1024，所以这里就让它提前退出循环
                    break;
                }
                //路径
                Image  img = Image.getInstance(source[i]);
                //获得宽高
                Float h = img.getHeight();
                Float w = img.getWidth();
                //统一压缩
                Integer percent = getPercent(h, w);
                //图片居中
                img.setAlignment(Image.MIDDLE);
                //百分比显示图
                img.scalePercent(percent);
                //设置高和宽的比例
                doc.add(img);
            }*/
            // 关闭文档
            if (doc != null) {
                doc.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 压缩
     *
     * @param
     */
    public static Integer getPercent(Float h, Float w) {
        Integer g = 0;
        Float g2 = 0.0f;
        g2 = 480 / w * 40;
        g = Math.round(g2);
        return g;
    }

    public static void main(String[] args) throws Exception {
        PdfUtils.pdfToImage("D:\\1.pdf", "D:\\test\\image");
    }
}
